library(ggplot2)
library(tidyverse)
library(GGally)
library(ggpubr)
#load the dataframes for the figure
remove cells in the edges : pos.x > 45 & < 1150 pos.y >
45 & < 1000 ##add the replicate info
aic.df <- aic.df %>%
mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
str_split(cell.id, "_", simplify = T)[,3]),
colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1",
exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))
aic.df <- aic.df %>%
mutate(colony = ifelse(degron == "stable" & red == "pup1-rfp",
case_when(exp.field %in% c("20min_s4", "20min_s5") ~ "Replicate 1",
exp.field %in% c("20min_s6", "20min_s7") ~ "Replicate 2",
exp.field %in% c("20min_s8", "20min_s9") ~ "Replicate 3"), colony))
# filter(value < 0.05)
##Cellular attributes
pup1.cell.attr <- read_csv("~/plots/all_data/all_pup1_cell_attr.csv")
Rows: 19396 Columns: 29
── Column specification ───────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (4): cell.id, degron, red, treatment
dbl (25): gfp.mean.bg.af.sub.new, gfp.sum.bg.af.sub, area, area.puncta, BB_B, BB_C, Elip_B, Elip_C, no.of.voxels, pos.x, pos.y, spherac...
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
###pup1-RFP background
pup1.cell.attr <- pup1.cell.attr %>%
mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
str_split(cell.id, "_", simplify = T)[,3]),
colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1",
exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))
pup1.cell.attr <- pup1.cell.attr %>%
mutate(colony = ifelse(degron == "stable" & red == "pup1-rfp",
case_when(exp.field %in% c("20min_s4", "20min_s5") ~ "Replicate 1",
exp.field %in% c("20min_s6", "20min_s7") ~ "Replicate 2",
exp.field %in% c("20min_s8", "20min_s9") ~ "Replicate 3"), colony))
pup1.cell.attr %>%
mutate(exp = str_split(exp.field, "_", simplify = T)[,1]) %>% split(.$exp)
$`20min`
$`40min`
$`60min`
NA
Adding the gfp.sum column for the stable GFP experiment
pup1.cell.attr <- read_csv("~/plots/pup1-rfp-gfp-decay/4-28-21-8hrGFP/data/gfp_stable_filtered.csv") %>%
filter(image.no == 1) %>%
dplyr::select(cell.id, gfpSumBgAFsub) %>%
mutate(cell.id = paste0(cell.id,"_","stable_pup1-rfp_none")) %>%
dplyr::rename("gfp.sum.bg.af.sub" = "gfpSumBgAFsub") %>%
left_join(pup1.cell.attr %>%
filter(degron == "stable") %>%
dplyr::select(-gfp.sum.bg.af.sub),., by = "cell.id") %>%
bind_rows(pup1.cell.attr %>%
filter(degron != "stable"),.)
removing multiple entries of the cell because some cell have more
than one,
multiple.pup1 <- pup1.cell.attr %>%
mutate(dapi.mean.bg.sub.puncta = ifelse(is.na(dapi.mean.bg.sub.puncta), 0, dapi.mean.bg.sub.puncta) ,
rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0 , rfp.mean.bg.sub.puncta)) %>%
filter(rfp.mean.bg.sub.puncta > 0) %>%
group_by(cell.id) %>%
tally() %>%
filter(n>1)
pup1.cell.attr<- pup1.cell.attr %>%
group_by(cell.id) %>%
mutate(rfp.mean.bg.sub.puncta = ifelse(cell.id %in% multiple.pup1$cell.id , mean(rfp.mean.bg.sub.puncta), rfp.mean.bg.sub.puncta),
rfp.sum.bg.sub.puncta = ifelse(cell.id %in% multiple.pup1$cell.id, sum(rfp.mean.bg.sub.puncta), rfp.sum.bg.sub.puncta)) %>%
distinct(cell.id, .keep_all = TRUE)
#proteasome inhibition experiments
protInhi.attr <- read_csv("~/plots/all_data/all_mg135_attr.csv") %>%
rename("cell.id" = "unique.trackID") %>%
filter(timepoint == 1) %>%
mutate(cell.id = paste0(cell.id ,"_",degron,"_",red,"_",treatment)) %>%
mutate(exp.field = paste0(str_split(cell.id, "_", simplify = T)[,2],"_",
str_split(cell.id, "_", simplify = T)[,3]),
colony = case_when(exp.field %in% c("20min_s3", "20min_s4") ~ "Replicate 1",
exp.field %in% c("20min_s5", "20min_s6") ~ "Replicate 2",
exp.field %in% c("20min_s7", "20min_s8" , "20min_s9") ~ "Replicate 3"))
multiple.proInh <- protInhi.attr %>%
mutate(dapi.mean.bg.sub.puncta = ifelse(is.na(dapi.mean.bg.sub.puncta), 0, dapi.mean.bg.sub.puncta) ,
rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0 , rfp.mean.bg.sub.puncta)) %>%
filter(rfp.mean.bg.sub.puncta > 0) %>%
group_by(cell.id) %>%
tally() %>%
filter(n>1)
protInhi.attr <- protInhi.attr %>%
group_by(cell.id) %>%
mutate(rfp.mean.bg.sub.puncta = ifelse(cell.id %in% multiple.proInh$cell.id , mean(rfp.mean.bg.sub.puncta), rfp.mean.bg.sub.puncta),
rfp.sum.bg.sub.puncta = ifelse(cell.id %in% multiple.proInh$cell.id, sum(rfp.mean.bg.sub.puncta), rfp.sum.bg.sub.puncta)) %>%
distinct(cell.id, .keep_all = TRUE)
Adding the protein inhibition experiment data
pup1.proInhi.attr <- pup1.cell.attr %>%
bind_rows(.,protInhi.attr %>%
dplyr::select(-time,
-timepoint,
-image.no,
-ln.gfp,
-ln.gfp.dif,
-trackID,
-gfp.intensity.center,
-gfp.int.mean,
-gfp.int.median,
-gfp.int.sum,
-no.of.triangles,
-field,
-time.dif.gfp,
-real.time.gfp,
-sample,
-avg.gfp.bg,
-Min_gfp,
-gfp.mean.bg.sub,
-value,
-t80,
-t95,
-threshold,
-threshold_95,
-gfp.mean.bg.af.sub,
-threshold_80,
-Mean_gfp,
-image,
-experiment,
-gfp.sum.bg.sub))
#keeping the parameters estimated from the 2-parameter with
maturation model
#only dy.dm
dy.pup1.rep1.mat <- aic.df %>%
filter(red == "pup1-rfp") %>%
filter(ifelse(degron %in% c("stable","stable.2","stable.3"), dy < 0.1, dy < 0.5)) %>%
group_by(cell.id) %>%
filter(model == "dy.dm") %>%
mutate(dm = ifelse(is.na(dm), Inf, dm)) %>%
filter( dm > 0.000015)
#count the number of cells in each experiment
dy.pup1.rep1.mat %>% group_by(degron, treatment) %>% tally()
#creating the df for the MLR
mlr.df <- dy.pup1.rep1.mat %>%
#left join with the df with cellular attributes
left_join(.,pup1.proInhi.attr, by = c("cell.id","red","treatment","degron", "exp.field","colony")) %>%
#remove cells with no rfp puncta info
mutate(rfp.mean.bg.sub.puncta = ifelse(is.na(rfp.mean.bg.sub.puncta), 0, rfp.mean.bg.sub.puncta)) %>%
filter(rfp.mean.bg.sub.puncta > 0)
#checking how many cells there are in each experiment
mlr.df %>% group_by(degron, treatment) %>% tally()
##Removing the columns that I wont regress upon
mlr.df <- mlr.df %>%
filter(pos.x > 45 & pos.x < 1150,
pos.y > 45 & pos.y < 1000) %>%
dplyr::select(-f,
-rfp.mean.af.sub.puncta,
-rfp.sum.af.sub.puncta,
-dapi.sum.af.sub.puncta,
-dapi.mean.af.sub.puncta,
-model,
-k,
-fevals,
-gevals,
-niter,
-convcode,
-kkt1,
-kkt2,
-value,
-xtime,
# -treatment,
-rfp.mean.bg.sub,
-rfp.sum.bg.sub,
-dapi.mean.bg.sub,
-dapi.sum.bg.sub,
-dapi.mean.bg.sub.puncta,
-area.puncta,
-BB_B,
-BB_C,
-pos.x,
-pos.y,
-gfp.sum.bg.af.sub,
-rfp.sum.bg.sub.puncta,
-no.of.voxels,
-volume,
-spheracity) %>%
mutate(shape = Elip_B/Elip_C,
t.half = log(2)/dy) %>%
ungroup() %>%
dplyr::select(-cell.id,
-red,
-exp.field,
-aic,
-Elip_B,
-Elip_C,
-exp)
#Regressors to use for MLR
regressors <- c("dm",
"gfp.mean.bg.af.sub.new",
# "gfp.sum.bg.af.sub",
"area",
# "no.of.voxels",
# "spheracity",
# "volume",
"rfp.mean.bg.sub.puncta",
# "rfp.sum.bg.sub.puncta",
"dapi.sum.bg.sub.puncta",
"shape")
#df where the two experiments of cln2 and stable-GFP are clubbed
mlr.df2 <- mlr.df %>%
filter(degron %in% c("cln2.3","mODC.2","stable.3","stable.2","cln2.4")) %>%
mutate(degron = case_when(degron %in% c("cln2.3","cln2.2","cln2","cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2", "mODC") ~ "yeGFP-mODC",
degron %in% c("stable","stable.2","stable.3") ~ "yeGFP"))
#df to be used with step function
temp.df.list <- mlr.df2 %>%
filter(treatment == "none") %>%
# mutate( dm = log10(dm)) %>%
split(.$degron)
#using stepAIC from MASS
full.stepAIC.mass %>% map(.,broom::tidy)
$`GFP-CLN2`
$`GFP-mODC`
$yeGFP
NA
#step AIC with all the fp markers + cell shape
full.stepAIC <- lapply(temp.df.list, function(a){
n <- nrow(a)
step(lm(t.half ~ ., data = a %>%
dplyr::select(regressors,
t.half,
-dy,
-treatment)),
direction = "backward",
trace = T,
# k = log(n),
k =2 ) #k = 2 when small dataset and k = log(n) where n = no. of observations for when the dataset is large
})
Note: Using an external vector in selections is ambiguous.
ℹ Use `all_of(regressors)` instead of `regressors` to silence this message.
ℹ See <https://tidyselect.r-lib.org/reference/faq-external-vector.html>.
This message is displayed once per session.
Start: AIC=5023.53
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta + shape
Df Sum of Sq RSS AIC
- rfp.mean.bg.sub.puncta 1 32.7 36232 5023.0
- shape 1 38.8 36239 5023.3
- area 1 39.3 36239 5023.3
<none> 36200 5023.5
- dm 1 247.6 36447 5032.5
- dapi.sum.bg.sub.puncta 1 918.2 37118 5061.8
- gfp.mean.bg.af.sub.new 1 7805.7 44006 5335.7
Step: AIC=5022.98
t.half ~ dm + gfp.mean.bg.af.sub.new + area + dapi.sum.bg.sub.puncta +
shape
Df Sum of Sq RSS AIC
- shape 1 37.2 36270 5022.6
<none> 36232 5023.0
- area 1 89.4 36322 5024.9
- dm 1 259.8 36492 5032.5
- dapi.sum.bg.sub.puncta 1 970.8 37203 5063.5
- gfp.mean.bg.af.sub.new 1 7803.3 44036 5334.8
Step: AIC=5022.63
t.half ~ dm + gfp.mean.bg.af.sub.new + area + dapi.sum.bg.sub.puncta
Df Sum of Sq RSS AIC
<none> 36270 5022.6
- area 1 82.2 36352 5024.3
- dm 1 249.7 36519 5031.7
- dapi.sum.bg.sub.puncta 1 1048.1 37318 5066.5
- gfp.mean.bg.af.sub.new 1 7848.3 44118 5335.8
Start: AIC=1261.28
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta + shape
Df Sum of Sq RSS AIC
- shape 1 1.67 3519.1 1260.1
- dm 1 2.15 3519.6 1260.3
<none> 3517.5 1261.3
- rfp.mean.bg.sub.puncta 1 5.47 3522.9 1261.8
- area 1 85.84 3603.3 1299.2
- dapi.sum.bg.sub.puncta 1 89.54 3607.0 1300.9
- gfp.mean.bg.af.sub.new 1 479.97 3997.4 1471.2
Step: AIC=1260.06
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta
Df Sum of Sq RSS AIC
- dm 1 2.17 3521.3 1259.1
<none> 3519.1 1260.1
- rfp.mean.bg.sub.puncta 1 5.05 3524.2 1260.4
- area 1 84.64 3603.8 1297.4
- dapi.sum.bg.sub.puncta 1 87.90 3607.0 1298.9
- gfp.mean.bg.af.sub.new 1 482.37 4001.5 1470.9
Step: AIC=1259.08
t.half ~ gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta
Df Sum of Sq RSS AIC
<none> 3521.3 1259.1
- rfp.mean.bg.sub.puncta 1 5.13 3526.4 1259.5
- area 1 85.97 3607.3 1297.0
- dapi.sum.bg.sub.puncta 1 87.30 3608.6 1297.7
- gfp.mean.bg.af.sub.new 1 493.27 4014.6 1474.3
Start: AIC=922.36
t.half ~ dm + gfp.mean.bg.af.sub.new + area + rfp.mean.bg.sub.puncta +
dapi.sum.bg.sub.puncta + shape
Df Sum of Sq RSS AIC
<none> 2628.7 922.36
- shape 1 7.60 2636.3 924.18
- area 1 49.53 2678.2 945.06
- rfp.mean.bg.sub.puncta 1 56.77 2685.5 948.63
- dapi.sum.bg.sub.puncta 1 93.01 2721.7 966.37
- dm 1 105.69 2734.4 972.52
- gfp.mean.bg.af.sub.new 1 561.29 3190.0 1176.40
full.stepAIC %>%
map(., broom::glance) %>%
bind_rows(.id = "sample")
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3"))
full.stepAIC %>%
map(., broom::tidy)
$yeGFP
$`yeGFP-CLN2`
$`yeGFP-mODC`
# bind_rows(.id = "sample") %>%
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3"),
# p.value < 0.05) %>%
full.stepAIC %>%
map(.,function(a){
a$anova
}) %>%
bind_rows(.,.id = "degron") %>%
mutate(Step = as.character(Step),
Step = ifelse(Step == "", "Full",Step)) %>%
group_by(degron) %>%
mutate(del.aic = AIC[1]-AIC)
full.stepAIC.fp %>%
map(.,function(a){
a$anova
}) %>%
bind_rows(.,.id = "degron") %>%
mutate(Step = as.character(Step),
Step = ifelse(Step == "", "Full",Step)) %>%
group_by(degron) %>%
mutate(del.aic = AIC[1]-AIC)
NA
NA
#step AIC with only the fluorescent markers
#looking at which regressor contributes to the overall variability
full.stepAIC.fp %>%
map(., broom::tidy)
$`GFP-CLN2`
$`GFP-mODC`
$yeGFP
NA
Variance in t-half explained by each regressor using anova
var.explained
$yeGFP
$`yeGFP-CLN2`
$`yeGFP-mODC`
NA
#plotting the variance explained

#plots:
gfp.6.cor.plt
`geom_smooth()` using formula 'y ~ x'

with protein inhibition
mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c("mODC")) %>%
# filter(!(treatment %in% c("none", "dmso1","50uM")),
# ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
dplyr::select(t.half,
regressors,
degron,
treatment) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DNA" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
pivot_longer(cols = 2:7) %>%
mutate(degron = case_when(
degron %in% c("mODC") ~ "yeGFP-mODC"),
treatment = factor(treatment, levels = c("none","dmso1","dmso2","1uM","2.5uM","5uM","50uM"))) %>%
filter(!(name %in% c("shape","dm")),
!(treatment %in% c("none","dmso1","50uM")),
t.half < 130) %>%
ggplot(., aes(x = value, y = t.half)) +
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_grid(treatment ~ name, scales = "free") +
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none")+
ylab("Half-Life [min.]")+
xlab("A.U")
Warning: Ignoring unknown parameters: guides
`geom_smooth()` using formula 'y ~ x'

#stepAIC with proteasome inhibition experiments With all fp
regressors
temp.df.list.dmso <- mlr.df %>%
filter(treatment != "none", t.half < 130) %>%
split(.$treatment)
full.stepAIC.fp.dmso <- lapply(temp.df.list.dmso, function(a){
step(lm(t.half ~ ., data = a %>%
dplyr::select(regressors.fp,
t.half,
-dy,
-treatment)),
direction = "backward", trace = T)
})
with fp regressors + celluar shape
temp.df.list.dmso <- mlr.df %>%
filter(treatment != "none", t.half < 130) %>%
split(.$treatment)
full.stepAIC.dmso <- lapply(temp.df.list.dmso, function(a){
step(lm(t.half ~ ., data = a %>%
dplyr::select(regressors.fp,
t.half,
-dy,
-treatment)),
direction = "backward", trace = T)
})
Variance in t-half explained by each regressor
full.stepAIC.dmso %>%
map(., anova %>% as.data.frame) %>%
bind_rows(.id = "sample") %>%
rownames_to_column(var = "predictor") %>%
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>%
group_by(sample) %>%
mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100) %>%
split(.$sample)
full.stepAIC.fp.dmso %>%
map(., anova %>% as.data.frame) %>%
bind_rows(.id = "sample") %>%
rownames_to_column(var = "predictor") %>%
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>%
group_by(sample) %>%
mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100) %>%
split(.$sample)
full.stepAIC.dmso %>%
map(., anova %>% as.data.frame) %>%
bind_rows(.id = "sample") %>%
rownames_to_column(var = "predictor") %>%
# filter(sample %in% c("mODC.2","cln2.3","cln2.4","stable.2","stable.3")) %>%
group_by(sample) %>%
mutate(var.exp = (value.Sum.Sq/sum(value.Sum.Sq))*100,
predictor = str_split(predictor, pattern = "\\.\\.\\.", simplify = T)[,1],
predictor = case_when(predictor == "gfp.mean.bg.af.sub.new" ~ "GFP" ,
predictor == "area" ~ "Area",
predictor == "rfp.mean.bg.sub.puncta" ~ "Pup1",
predictor == "dapi.sum.bg.sub.puncta" ~ "DNA" ,
predictor == "shape" ~ "Shape",
predictor == "dm" ~ "Rate of Maturation"
,
TRUE~predictor)) %>%
split(.$sample)
$`1uM`
$`2.5uM`
$`50uM`
$`5uM`
$dmso1
$dmso2
NA
mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c ("mODC") ) %>%
filter(!(treatment %in% c("none", "dmso1","50uM")),
ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
dplyr::select(t.half,
regressors,
degron,
treatment) %>%
ggplot(.,aes(x = area, y = rfp.mean.bg.sub.puncta))+
geom_point()+
geom_smooth(method = "lm", se = F)+
facet_wrap(~treatment)+
stat_cor()
#ggpairs
gfp.area.cor.ggPair
$`yeGFP-mODC`
plot: [1,1] [====>----------------------------------------------------------------------------------] 6% est: 0s
plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 1s
plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s
plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s
plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s
plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 1s
plot: [2,4] [===========================================>-------------------------------------------] 50% est: 1s
plot: [3,1] [================================================>--------------------------------------] 56% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,2] [=====================================================>---------------------------------] 62% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,3] [===========================================================>---------------------------] 69% est: 0s
plot: [3,4] [================================================================>----------------------] 75% est: 0s
plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,4] [=======================================================================================]100% est: 0s
$`yeGFP-CLN2`
plot: [1,1] [====>----------------------------------------------------------------------------------] 6% est: 0s
plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 0s
plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s
plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s
plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s
plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 1s
plot: [2,4] [===========================================>-------------------------------------------] 50% est: 1s
plot: [3,1] [================================================>--------------------------------------] 56% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,2] [=====================================================>---------------------------------] 62% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [3,3] [===========================================================>---------------------------] 69% est: 0s
plot: [3,4] [================================================================>----------------------] 75% est: 0s
plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,4] [=======================================================================================]100% est: 0s
$yeGFP
plot: [1,1] [====>----------------------------------------------------------------------------------] 6% est: 0s
plot: [1,2] [==========>----------------------------------------------------------------------------] 12% est: 0s
plot: [1,3] [===============>-----------------------------------------------------------------------] 19% est: 1s
plot: [1,4] [=====================>-----------------------------------------------------------------] 25% est: 1s
plot: [2,1] [==========================>------------------------------------------------------------] 31% est: 1s `geom_smooth()` using formula 'y ~ x'
plot: [2,2] [================================>------------------------------------------------------] 38% est: 1s
plot: [2,3] [=====================================>-------------------------------------------------] 44% est: 0s
plot: [2,4] [===========================================>-------------------------------------------] 50% est: 0s
plot: [3,1] [================================================>--------------------------------------] 56% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [3,2] [=====================================================>---------------------------------] 62% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [3,3] [===========================================================>---------------------------] 69% est: 0s
plot: [3,4] [================================================================>----------------------] 75% est: 0s
plot: [4,1] [======================================================================>----------------] 81% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,2] [===========================================================================>-----------] 88% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,3] [=================================================================================>-----] 94% est: 0s `geom_smooth()` using formula 'y ~ x'
plot: [4,4] [=======================================================================================]100% est: 0s



ggsave(plot = gfp.area.cor.ggPair$`yeGFP-mODC`, filename = "gfp_mODC_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP-mODC`, filename = "gfp_mODC_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP-CLN2`, filename = "gfp_cln2_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP-CLN2`, filename = "gfp_cln2_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP`, filename = "gfp_4Cor_ggP.png", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
ggsave(plot = gfp.area.cor.ggPair$`yeGFP`, filename = "gfp_4Cor_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 4, height = 3.5)
test.ggP <- (wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$`yeGFP-mODC`))|wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$`yeGFP-CLN2`))| wrap_elements(ggmatrix_gtable(gfp.area.cor.ggPair$yeGFP)))+
plot_annotation(tag_levels = "A")
ggsave(plot = test.ggP, filename = "test_ggP.pdf", path = "~/plots/paper1/figures/fig_2/", width = 6.5, height = 3)
#area vs pup1 vs dna vs gfp
df_corSup_fig <- mlr.df %>%
filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
dplyr::select(t.half,
regressors,
degron) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DNA" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
dplyr::select(Area, DNA, `Pup1-tDimer`,GFP,degron ) %>%
mutate(
degron = case_when(
degron %in% c("cln2.3", "cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2") ~ "yeGFP-mODC",
degron %in% c("stable.2", "stable.3") ~ "yeGFP"
),
degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
)
area.pup1 <- df_corSup_fig %>%
filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = Area, y = `Pup1-tDimer`))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Pup1-tDimer [A.U]")+
xlab("Area [A.U]")
Warning: Ignoring unknown parameters: guides
dna.pup1 <- df_corSup_fig %>%
filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = DNA, y = `Pup1-tDimer`))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Pup1-tDimer [A.U]")+
xlab("DNA [A.U]")
Warning: Ignoring unknown parameters: guides
dna.area <- df_corSup_fig %>%
filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = DNA, y = Area))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
ylab("Area [A.U]")+
xlab("DNA [A.U]")
Warning: Ignoring unknown parameters: guides
gfpInt.cor.plt <- df_corSup_fig %>%
pivot_longer(cols = 1:3) %>%
# filter(degron == "yeGFP-mODC") %>%
ggplot(.,aes(x = value, y = GFP))+
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 3) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_wrap(degron~name, scales = "free")+
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none",
axis.line = element_line(size = 0.1))+
xlab("A.U")
Warning: Ignoring unknown parameters: guides
test_cor
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'

#Partial correlations ppcor
#partial correlations
ppCor.list <- mlr.df2 %>%
filter(treatment == "none") %>% split(.$degron) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
ppcor::pcor(a)
})
#correlations
cor.all <- mlr.df2 %>%
filter(treatment == "none") %>%
split(.$degron) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta,rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
cor(a)
})
ppCor.df <- ppCor.list %>%
map(.,function(a){
a$estimate %>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor) %>%
left_join(.,a$p.value%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
rename("p.value" = "t.half") %>%
dplyr::select(p.value, regressor), by = "regressor")
}) %>%
bind_rows(.id = "degron")
single.core.df <- cor.all %>%
map(.,function(a){
a%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor)
}) %>%
bind_rows(.id = "degron") %>%
rename("single.core"="t.half")
ppCoor.fig <- ppCor.df %>%
left_join(.,single.core.df, by = c("degron","regressor")) %>%
rename("Partial-Pariwise"="t.half",
"Standard-Pariwise" = "single.core") %>%
pivot_longer(cols = c("Partial-Pariwise","Standard-Pariwise")) %>%
mutate(regressor = case_when(regressor == "gfp.mean.bg.af.sub.new" ~ "GFP" ,
regressor == "area" ~ "Area",
regressor == "rfp.mean.bg.sub.puncta" ~ "Pup1",
regressor == "dapi.sum.bg.sub.puncta" ~ "DNA" ,
regressor == "t.half" ~ "half-life"),
degron = factor(degron, levels = c("yeGFP-mODC","yeGFP-CLN2","yeGFP")),
name = factor(name , levels = c("Standard-Pariwise", "Partial-Pariwise")),
sig = stars.pval(p.value),
sig = ifelse(sig == " ", "NS", sig)) %>%
# filter(p.value < 0.05) %>%
filter(regressor != "half-life") %>%
ggplot(.,aes(x = regressor , y = value, fill = name))+
geom_col(width = 0.5, position = "dodge")+
facet_wrap(~degron)+
geom_hline(yintercept = 0, size = 0.1)+
scale_y_continuous(breaks = seq(-0.5,0.5, by = 0.1))+
theme_pubr()+
theme(text = element_text(size = 8),
legend.key.size = unit(4,"mm"),
legend.position = "top",
axis.line = element_line(size = 0.1),
strip.background = element_blank())+
scale_fill_manual(values = c("lightsteelblue4" ," steelblue4"), name = NULL)+
ylab("Correlation with Half-life ")+
xlab("Cellular features")+
labs(title = "C")
ppCoor.fig

#patchwork for 4 cellular features (area, gfp, dapi, pup1) and
t-half
gfp.4cor.hf.ppCor.plt
`geom_smooth()` using formula 'y ~ x'

ggsave(plot = gfp.4cor.hf.ppCor.plt, filename = "gfp_4cor_halfLife_ppcor.png", path = "~/plots/paper1/figures/fig_2/", width = 7, height = 9)
`geom_smooth()` using formula 'y ~ x'
#with protein inhibion
ppCor.PrtIn.list <- mlr.df %>%
filter(treatment != "none") %>%
filter(ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
split(.$treatment) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
ppcor::pcor(a)
})
cor.PrtIn.all <- mlr.df %>%
filter(treatment != "none") %>%
filter(ifelse(treatment == "5uM", t.half < 138.6294, t.half == t.half)) %>%
split(.$treatment) %>%
map(.,function(a){
a <- a %>%
dplyr::select(t.half, area, dapi.sum.bg.sub.puncta, rfp.mean.bg.sub.puncta, gfp.mean.bg.af.sub.new) %>%
na.omit()
cor(a)
})
ppCor.PrtIn.df <- ppCor.PrtIn.list %>%
map(.,function(a){
a$estimate %>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor) %>%
left_join(.,a$p.value%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
rename("p.value" = "t.half") %>%
dplyr::select(p.value, regressor), by = "regressor")
}) %>%
bind_rows(.id = "treatment")
single.core.Prtn.df <- cor.PrtIn.all %>%
map(.,function(a){
a%>%
as.data.frame() %>%
rownames_to_column(var = "regressor") %>%
dplyr::select(t.half, regressor)
}) %>%
bind_rows(.id = "treatment") %>%
rename("single.core"="t.half")
correlation of pup1 with mODC with treated with proteasome
inhibitors

#when you normalize pup1 with the area
mlr.df %>%
mutate(dm = log10(dm)) %>%
filter(degron %in% c("mODC.2", "cln2.3", "cln2.4", "stable.2", "stable.3")) %>%
dplyr::select(t.half,
regressors,
degron) %>%
rename(
"GFP" = "gfp.mean.bg.af.sub.new",
"Pup1-tDimer" = "rfp.mean.bg.sub.puncta",
"DNA" = "dapi.sum.bg.sub.puncta",
"Area" = "area"
) %>%
mutate(norm.pup1 = `Pup1-tDimer`/Area) %>%
pivot_longer(cols = c(2:7,9)) %>%
mutate(degron = case_when(
degron %in% c("cln2.3", "cln2.2", "cln2", "cln2.4") ~ "yeGFP-CLN2",
degron %in% c("mODC.2", "mODC") ~ "yeGFP-mODC",
degron %in% c("stable", "stable.2", "stable.3") ~ "yeGFP"
),
degron = factor(degron , levels = c("yeGFP-mODC", "yeGFP-CLN2", "yeGFP"))
) %>%
filter(!(name %in% c("shape","dm"))) %>%
ggplot(., aes(x = value, y = t.half)) +
ggpointdensity::geom_pointdensity(size = 0.2, guides = F) +
stat_cor(size = 2) +
geom_smooth(method = "lm", se = FALSE, color = "red4", size = 0.5)+
facet_wrap(degron ~ name, scales = "free", ncol = 4) +
theme_bw() +
labs(x = NULL) +
theme(text = element_text(size = 8),
axis.text.x = element_text(angle = 30),
legend.key.size = unit(2,"mm"),
legend.position = "none")+
ylab("Half-Life [min.]")+
xlab("A.U")
LS0tCnRpdGxlOiAiQ29ycmVsYXRpb25zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KEdHYWxseSkKbGlicmFyeShnZ3B1YnIpCmxpYnJhcnkobGF0ZXgyZXhwKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShndG9vbHMpCmBgYAoKI2xvYWQgdGhlIGRhdGFmcmFtZXMgZm9yIHRoZSBmaWd1cmUKYGBge3J9CmFpYy5kZiA8LSByZWFkX2Nzdigifi9wbG90cy9hbGxfZGF0YS9haWMuY3N2IikKYGBgCgoKcmVtb3ZlIGNlbGxzIGluIHRoZSBlZGdlcyA6CnBvcy54ID4gNDUgJiA8IDExNTAKcG9zLnkgPiA0NSAmIDwgMTAwMAojI2FkZCB0aGUgcmVwbGljYXRlIGluZm8gCmBgYHtyfQphaWMuZGYgPC0gYWljLmRmICU+JSAKICBtdXRhdGUoZXhwLmZpZWxkID0gcGFzdGUwKHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDJdLCJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDNdKSwKICAgIGNvbG9ueSA9IGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zMyIsICIyMG1pbl9zNCIpIH4gIlJlcGxpY2F0ZSAxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNSIsICIyMG1pbl9zNiIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M3IiwgIjIwbWluX3M4IiAsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIikpCgphaWMuZGYgPC0gYWljLmRmICU+JSAKICBtdXRhdGUoY29sb255ID0gaWZlbHNlKGRlZ3JvbiA9PSAic3RhYmxlIiAmIHJlZCA9PSAicHVwMS1yZnAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNCIsICIyMG1pbl9zNSIpIH4gIlJlcGxpY2F0ZSAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNiIsICIyMG1pbl9zNyIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zOCIsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIiksIGNvbG9ueSkpIAogIApgYGAKCiMjQ2VsbHVsYXIgYXR0cmlidXRlcwpgYGB7cn0KcHVwMS5jZWxsLmF0dHIgPC0gcmVhZF9jc3YoIn4vcGxvdHMvYWxsX2RhdGEvYWxsX3B1cDFfY2VsbF9hdHRyLmNzdiIpCmBgYAoKIyMjcHVwMS1SRlAgYmFja2dyb3VuZApgYGB7cn0KcHVwMS5jZWxsLmF0dHIgPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIG11dGF0ZShleHAuZmllbGQgPSBwYXN0ZTAoc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssMl0sIl8iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3NwbGl0KGNlbGwuaWQsICJfIiwgc2ltcGxpZnkgPSBUKVssM10pLAogICAgY29sb255ID0gY2FzZV93aGVuKGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3MzIiwgIjIwbWluX3M0IikgfiAiUmVwbGljYXRlIDEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M1IiwgIjIwbWluX3M2IikgfiAiUmVwbGljYXRlIDIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwLmZpZWxkICVpbiUgYygiMjBtaW5fczciLCAiMjBtaW5fczgiICwgIjIwbWluX3M5IikgfiAiUmVwbGljYXRlIDMiKSkKCnB1cDEuY2VsbC5hdHRyIDwtIHB1cDEuY2VsbC5hdHRyICU+JSAKICBtdXRhdGUoY29sb255ID0gaWZlbHNlKGRlZ3JvbiA9PSAic3RhYmxlIiAmIHJlZCA9PSAicHVwMS1yZnAiLCAKICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNCIsICIyMG1pbl9zNSIpIH4gIlJlcGxpY2F0ZSAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNiIsICIyMG1pbl9zNyIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zOCIsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIiksIGNvbG9ueSkpIAogIApgYGAKCmBgYHtyfQojcmVtb3ZpbmcgdGhlIDQwbWluIGFuZCA2MG1pbiBleHBlcmltZW50cyBmcm9tIHRoZSBzdGFibGUgZ2ZwIGV4cGVyaW1lbnRzCnB1cDEuY2VsbC5hdHRyIDwtIHB1cDEuY2VsbC5hdHRyICU+JQogIG11dGF0ZShleHAgPSBzdHJfc3BsaXQoZXhwLmZpZWxkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDFdKSAlPiUgc3BsaXQoLiRleHApCiAgZmlsdGVyKGV4cCA9PSAiMjBtaW4iKQpgYGAKCkFkZGluZyB0aGUgZ2ZwLnN1bSBjb2x1bW4gZm9yIHRoZSBzdGFibGUgR0ZQIGV4cGVyaW1lbnQKYGBge3J9CnB1cDEuY2VsbC5hdHRyIDwtIHJlYWRfY3N2KCJ+L3Bsb3RzL3B1cDEtcmZwLWdmcC1kZWNheS80LTI4LTIxLThockdGUC9kYXRhL2dmcF9zdGFibGVfZmlsdGVyZWQuY3N2IikgJT4lIAogIGZpbHRlcihpbWFnZS5ubyA9PSAxKSAlPiUgCiAgZHBseXI6OnNlbGVjdChjZWxsLmlkLCBnZnBTdW1CZ0FGc3ViKSAlPiUgCiAgbXV0YXRlKGNlbGwuaWQgPSBwYXN0ZTAoY2VsbC5pZCwiXyIsInN0YWJsZV9wdXAxLXJmcF9ub25lIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKCJnZnAuc3VtLmJnLmFmLnN1YiIgPSAiZ2ZwU3VtQmdBRnN1YiIpICU+JSAKICBsZWZ0X2pvaW4ocHVwMS5jZWxsLmF0dHIgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihkZWdyb24gPT0gInN0YWJsZSIpICU+JSAKICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KC1nZnAuc3VtLmJnLmFmLnN1YiksLiwgYnkgPSAiY2VsbC5pZCIpICU+JSAKICBiaW5kX3Jvd3MocHVwMS5jZWxsLmF0dHIgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihkZWdyb24gIT0gInN0YWJsZSIpLC4pCmBgYAoKcmVtb3ZpbmcgbXVsdGlwbGUgZW50cmllcyBvZiB0aGUgY2VsbCBiZWNhdXNlIHNvbWUgY2VsbCBoYXZlIG1vcmUgdGhhbiBvbmUsIApgYGB7cn0KbXVsdGlwbGUucHVwMSA8LSBwdXAxLmNlbGwuYXR0ciAlPiUgCiAgbXV0YXRlKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGlzLm5hKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhKSwgMCwgZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEpICwgCiAgICAgICAgIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoaXMubmEocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksIDAgLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSkgJT4lIAogIGZpbHRlcihyZnAubWVhbi5iZy5zdWIucHVuY3RhID4gMCkgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICB0YWxseSgpICU+JSAKICBmaWx0ZXIobj4xKQoKcHVwMS5jZWxsLmF0dHI8LSBwdXAxLmNlbGwuYXR0ciAlPiUgCiAgZ3JvdXBfYnkoY2VsbC5pZCkgJT4lIAogIG11dGF0ZShyZnAubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGNlbGwuaWQgJWluJSBtdWx0aXBsZS5wdXAxJGNlbGwuaWQgLCBtZWFuKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEpLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSwKICAgICAgICAgcmZwLnN1bS5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGNlbGwuaWQgJWluJSBtdWx0aXBsZS5wdXAxJGNlbGwuaWQsIHN1bShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLnN1bS5iZy5zdWIucHVuY3RhKSkgJT4lIAogICAgZGlzdGluY3QoY2VsbC5pZCwgLmtlZXBfYWxsID0gVFJVRSkgCiAgCmBgYAoKI3Byb3RlYXNvbWUgaW5oaWJpdGlvbiBleHBlcmltZW50cwpgYGB7cn0KcHJvdEluaGkuYXR0ciA8LSByZWFkX2Nzdigifi9wbG90cy9hbGxfZGF0YS9hbGxfbWcxMzVfYXR0ci5jc3YiKSAlPiUgCiAgcmVuYW1lKCJjZWxsLmlkIiA9ICJ1bmlxdWUudHJhY2tJRCIpICU+JSAKICBmaWx0ZXIodGltZXBvaW50ID09IDEpICU+JSAKICBtdXRhdGUoY2VsbC5pZCA9IHBhc3RlMChjZWxsLmlkICwiXyIsZGVncm9uLCJfIixyZWQsIl8iLHRyZWF0bWVudCkpICU+JSAKICBtdXRhdGUoZXhwLmZpZWxkID0gcGFzdGUwKHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDJdLCJfIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zcGxpdChjZWxsLmlkLCAiXyIsIHNpbXBsaWZ5ID0gVClbLDNdKSwKICAgIGNvbG9ueSA9IGNhc2Vfd2hlbihleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zMyIsICIyMG1pbl9zNCIpIH4gIlJlcGxpY2F0ZSAxIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHAuZmllbGQgJWluJSBjKCIyMG1pbl9zNSIsICIyMG1pbl9zNiIpIH4gIlJlcGxpY2F0ZSAyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cC5maWVsZCAlaW4lIGMoIjIwbWluX3M3IiwgIjIwbWluX3M4IiAsICIyMG1pbl9zOSIpIH4gIlJlcGxpY2F0ZSAzIikpCgptdWx0aXBsZS5wcm9JbmggPC0gcHJvdEluaGkuYXR0ciAlPiUgCiAgbXV0YXRlKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhID0gaWZlbHNlKGlzLm5hKGRhcGkubWVhbi5iZy5zdWIucHVuY3RhKSwgMCwgZGFwaS5tZWFuLmJnLnN1Yi5wdW5jdGEpICwgCiAgICAgICAgIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoaXMubmEocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksIDAgLCByZnAubWVhbi5iZy5zdWIucHVuY3RhKSkgJT4lIAogIGZpbHRlcihyZnAubWVhbi5iZy5zdWIucHVuY3RhID4gMCkgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICB0YWxseSgpICU+JSAKICBmaWx0ZXIobj4xKQoKcHJvdEluaGkuYXR0ciA8LSBwcm90SW5oaS5hdHRyICU+JSAKICBncm91cF9ieShjZWxsLmlkKSAlPiUgCiAgbXV0YXRlKHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEgPSBpZmVsc2UoY2VsbC5pZCAlaW4lIG11bHRpcGxlLnByb0luaCRjZWxsLmlkICwgbWVhbihyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSksCiAgICAgICAgIHJmcC5zdW0uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShjZWxsLmlkICVpbiUgbXVsdGlwbGUucHJvSW5oJGNlbGwuaWQsIHN1bShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgcmZwLnN1bS5iZy5zdWIucHVuY3RhKSkgJT4lIAogICAgZGlzdGluY3QoY2VsbC5pZCwgLmtlZXBfYWxsID0gVFJVRSkgIAogIApgYGAKCkFkZGluZyB0aGUgcHJvdGVpbiBpbmhpYml0aW9uIGV4cGVyaW1lbnQgZGF0YQpgYGB7cn0KcHVwMS5wcm9JbmhpLmF0dHIgPC0gcHVwMS5jZWxsLmF0dHIgJT4lIAogIGJpbmRfcm93cyguLHByb3RJbmhpLmF0dHIgJT4lIAogICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoLXRpbWUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLXRpbWVwb2ludCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1pbWFnZS5ubywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtbG4uZ2ZwLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgIC1sbi5nZnAuZGlmLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLXRyYWNrSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludGVuc2l0eS5jZW50ZXIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludC5tZWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgLWdmcC5pbnQubWVkaWFuLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLmludC5zdW0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1uby5vZi50cmlhbmdsZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1maWVsZCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXRpbWUuZGlmLmdmcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXJlYWwudGltZS5nZnAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1zYW1wbGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1hdmcuZ2ZwLmJnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtTWluX2dmcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWdmcC5tZWFuLmJnLnN1YiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLXZhbHVlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdDgwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdDk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGhyZXNob2xkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGhyZXNob2xkXzk1LAogICAgICAgICAgICAgICAgICAgICAgICAgICAtZ2ZwLm1lYW4uYmcuYWYuc3ViLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtdGhyZXNob2xkXzgwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAtTWVhbl9nZnAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1pbWFnZSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgLWV4cGVyaW1lbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIC1nZnAuc3VtLmJnLnN1YikpCmBgYAoKCiNrZWVwaW5nIHRoZSBwYXJhbWV0ZXJzIGVzdGltYXRlZCBmcm9tIHRoZSAyLXBhcmFtZXRlciB3aXRoIG1hdHVyYXRpb24gbW9kZWwKYGBge3J9CiNvbmx5IGR5LmRtCmR5LnB1cDEucmVwMS5tYXQgPC0gYWljLmRmICU+JSAKICBmaWx0ZXIocmVkID09ICJwdXAxLXJmcCIpICU+JSAKICBmaWx0ZXIoaWZlbHNlKGRlZ3JvbiAlaW4lIGMoInN0YWJsZSIsInN0YWJsZS4yIiwic3RhYmxlLjMiKSwgZHkgPCAwLjEsIGR5IDwgMC41KSkgJT4lIAogIGdyb3VwX2J5KGNlbGwuaWQpICU+JSAKICBmaWx0ZXIobW9kZWwgPT0gImR5LmRtIikgJT4lIAogIG11dGF0ZShkbSA9IGlmZWxzZShpcy5uYShkbSksIEluZiwgZG0pKSAlPiUKICBmaWx0ZXIoIGRtID4gMC4wMDAwMTUpCmBgYAoKI2NvdW50IHRoZSBudW1iZXIgb2YgY2VsbHMgaW4gZWFjaCBleHBlcmltZW50IApgYGB7cn0KZHkucHVwMS5yZXAxLm1hdCAlPiUgZ3JvdXBfYnkoZGVncm9uLCB0cmVhdG1lbnQpICU+JSB0YWxseSgpCmBgYAojY3JlYXRpbmcgdGhlIGRmIGZvciB0aGUgTUxSCmBgYHtyfQptbHIuZGYgPC0gZHkucHVwMS5yZXAxLm1hdCAlPiUgCiAgI2xlZnQgam9pbiB3aXRoIHRoZSBkZiB3aXRoIGNlbGx1bGFyIGF0dHJpYnV0ZXMKICBsZWZ0X2pvaW4oLixwdXAxLnByb0luaGkuYXR0ciwgYnkgPSBjKCJjZWxsLmlkIiwicmVkIiwidHJlYXRtZW50IiwiZGVncm9uIiwgImV4cC5maWVsZCIsImNvbG9ueSIpKSAlPiUgCiAgI3JlbW92ZSBjZWxscyB3aXRoIG5vIHJmcCBwdW5jdGEgaW5mbyAKICBtdXRhdGUocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA9IGlmZWxzZShpcy5uYShyZnAubWVhbi5iZy5zdWIucHVuY3RhKSwgMCwgcmZwLm1lYW4uYmcuc3ViLnB1bmN0YSkpICU+JSAKICBmaWx0ZXIocmZwLm1lYW4uYmcuc3ViLnB1bmN0YSA+IDApCmBgYAoKI2NoZWNraW5nIGhvdyBtYW55IGNlbGxzIHRoZXJlIGFyZSBpbiBlYWNoIGV4cGVyaW1lbnQgCmBgYHtyfQptbHIuZGYgJT4lIGdyb3VwX2J5KGRlZ3JvbiwgdHJlYXRtZW50KSAlPiUgdGFsbHkoKQpgYGAKCiMjUmVtb3ZpbmcgdGhlIGNvbHVtbnMgdGhhdCBJIHdvbnQgcmVncmVzcyB1cG9uCmBgYHtyfQptbHIuZGYgPC0gbWxyLmRmICU+JSAKICBmaWx0ZXIocG9zLnggPiA0NSAmIHBvcy54IDwgMTE1MCwKICBwb3MueSA+IDQ1ICYgcG9zLnkgPCAxMDAwKSAlPiUKICBkcGx5cjo6c2VsZWN0KC1mLCAKICAgICAgICAgLXJmcC5tZWFuLmFmLnN1Yi5wdW5jdGEsCiAgICAgICAgIC1yZnAuc3VtLmFmLnN1Yi5wdW5jdGEsIAogICAgICAgICAtZGFwaS5zdW0uYWYuc3ViLnB1bmN0YSwKICAgICAgICAgLWRhcGkubWVhbi5hZi5zdWIucHVuY3RhLAogICAgICAgICAtbW9kZWwsIAogICAgICAgICAtaywKICAgICAgICAgLWZldmFscywKICAgICAgICAgLWdldmFscywgCiAgICAgICAgIC1uaXRlciwgCiAgICAgICAgIC1jb252Y29kZSwgCiAgICAgICAgIC1ra3QxLAogICAgICAgICAta2t0MiwKICAgICAgICAgLXZhbHVlLAogICAgICAgICAteHRpbWUsIAogICAgICAgICAjIC10cmVhdG1lbnQsCiAgICAgICAgIC1yZnAubWVhbi5iZy5zdWIsCiAgICAgICAgIC1yZnAuc3VtLmJnLnN1YiwKICAgICAgICAgLWRhcGkubWVhbi5iZy5zdWIsCiAgICAgICAgIC1kYXBpLnN1bS5iZy5zdWIsCiAgICAgICAgIC1kYXBpLm1lYW4uYmcuc3ViLnB1bmN0YSwKICAgICAgICAgLWFyZWEucHVuY3RhLAogICAgICAgICAtQkJfQiwKICAgICAgICAgLUJCX0MsCiAgICAgICAgIC1wb3MueCwKICAgICAgICAgLXBvcy55LAogICAgICAgICAtZ2ZwLnN1bS5iZy5hZi5zdWIsCiAgICAgICAgIC1yZnAuc3VtLmJnLnN1Yi5wdW5jdGEsCiAgICAgICAgIC1uby5vZi52b3hlbHMsCiAgICAgICAgIC12b2x1bWUsCiAgICAgICAgIC1zcGhlcmFjaXR5KSAlPiUgCiAgbXV0YXRlKHNoYXBlID0gRWxpcF9CL0VsaXBfQywgCiAgICAgICAgIHQuaGFsZiA9IGxvZygyKS9keSkgJT4lCiAgdW5ncm91cCgpICU+JQogIGRwbHlyOjpzZWxlY3QoLWNlbGwuaWQsIAogICAgICAgICAgICAgICAgLXJlZCwKICAgICAgICAgICAgICAgIC1leHAuZmllbGQsIAogICAgICAgICAgICAgICAgLWFpYywKICAgICAgICAgICAgICAgIC1FbGlwX0IsCiAgICAgICAgICAgICAgICAtRWxpcF9DLCAKICAgICAgICAgICAgICAgIC1leHApIApgYGAKCiNSZWdyZXNzb3JzIHRvIHVzZSBmb3IgTUxSCmBgYHtyfQpyZWdyZXNzb3JzIDwtIGMoImRtIiwKICAgICAgICAgICAgICAgICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICAgICAgICAgICAgICJhcmVhIiwKICAgICAgICAgICAgICAgICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgICAgICAgICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICAgICAgICAgICAgICJzaGFwZSIpCmBgYAoKCiNkZiB3aGVyZSB0aGUgdHdvIGV4cGVyaW1lbnRzIG9mIGNsbjIgYW5kIHN0YWJsZS1HRlAgYXJlIGNsdWJiZWQgCmBgYHtyfQptbHIuZGYyIDwtIG1sci5kZiAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoImNsbjIuMyIsIm1PREMuMiIsInN0YWJsZS4zIiwic3RhYmxlLjIiLCJjbG4yLjQiKSkgJT4lIAogIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oZGVncm9uICVpbiUgYygiY2xuMi4zIiwiY2xuMi4yIiwiY2xuMiIsImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVncm9uICVpbiUgYygibU9EQy4yIiwgIm1PREMiKSAgfiAieWVHRlAtbU9EQyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWdyb24gJWluJSBjKCJzdGFibGUiLCJzdGFibGUuMiIsInN0YWJsZS4zIikgfiAieWVHRlAiKSkgCiAgCmBgYAoKCiNkZiB0byBiZSB1c2VkIHdpdGggc3RlcCBmdW5jdGlvbgpgYGB7cn0KdGVtcC5kZi5saXN0IDwtIG1sci5kZjIgJT4lIAogICAgZmlsdGVyKHRyZWF0bWVudCA9PSAibm9uZSIpICU+JSAgCiAgIyBtdXRhdGUoIGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgc3BsaXQoLiRkZWdyb24pCmBgYAoKCiN1c2luZyBzdGVwQUlDIGZyb20gTUFTUwpgYGB7cn0KbGlicmFyeShNQVNTKQoKZnVsbC5zdGVwQUlDLm1hc3MgPC0gbGFwcGx5KHRlbXAuZGYubGlzdCwgZnVuY3Rpb24oYSl7CiAgbiA8LSBucm93KGEpCiAgbG0ub2JqIDwtIGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpCiAgICAgCiBzdGVwQUlDKG9iamVjdCA9IGxtLm9iaiwgCiAgICAgZGlyZWN0aW9uID0gImJhY2t3YXJkIiwgCiAgICAgdHJhY2UgPSBUKQp9KQpgYGAKCiNzdGVwIEFJQyB3aXRoIGFsbCB0aGUgZnAgbWFya2VycyArIGNlbGwgc2hhcGUgCmBgYHtyfQpmdWxsLnN0ZXBBSUMgPC0gbGFwcGx5KHRlbXAuZGYubGlzdCwgZnVuY3Rpb24oYSl7CiAgbiA8LSBucm93KGEpCiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCAKICAgICB0cmFjZSA9IFQsCiAgICAgIyBrID0gbG9nKG4pLAogICAgIGsgPTIgKSAjayA9IDIgd2hlbiBzbWFsbCBkYXRhc2V0IGFuZCBrID0gbG9nKG4pIHdoZXJlIG4gPSBuby4gb2Ygb2JzZXJ2YXRpb25zIGZvciB3aGVuIHRoZSBkYXRhc2V0IGlzIGxhcmdlCn0pCgoKYGBgCgoKI3N0ZXAgQUlDIHdpdGggb25seSB0aGUgZmx1b3Jlc2NlbnQgbWFya2VycyAKYGBge3J9CmZ1bGwuc3RlcEFJQy5mcCA8LSBsYXBwbHkodGVtcC5kZi5saXN0LCBmdW5jdGlvbihhKXsKICBuIDwtIG5yb3coYSkKIHN0ZXAobG0odC5oYWxmIH4gLiwgZGF0YSA9IGEgJT4lIAogICAgIGRwbHlyOjpzZWxlY3QocmVncmVzc29ycy5mcCwKICAgICAgICAgICAgICAgICAgIHQuaGFsZiwKICAgICAgICAgICAgICAgICAgIC1keSwgCiAgICAgICAgICAgICAgICAgICAtdHJlYXRtZW50KSksIAogICAgIGRpcmVjdGlvbiA9ICJiYWNrd2FyZCIsIAogICAgIHRyYWNlID0gVCwKICAgICBrID0gMikKfSkKCmBgYAoKVmFyaWFuY2UgaW4gdC1oYWxmIGV4cGxhaW5lZCBieSBlYWNoIHJlZ3Jlc3Nvcgp1c2luZyBhbm92YQoKYGBge3J9CnZhci5leHBsYWluZWQgPC0gZnVsbC5zdGVwQUlDICU+JSAKICBtYXAoLiwgYW5vdmEgJT4lIGFzLmRhdGEuZnJhbWUpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInByZWRpY3RvciIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICBncm91cF9ieShzYW1wbGUpICU+JSAKICBtdXRhdGUodmFyLmV4cCA9ICh2YWx1ZS5TdW0uU3Evc3VtKHZhbHVlLlN1bS5TcSkpKjEwMCwgCiAgICAgICAgIHByZWRpY3RvciA9IHN0cl9zcGxpdChwcmVkaWN0b3IsIHBhdHRlcm4gPSAiXFwuXFwuXFwuIiwgc2ltcGxpZnkgPSBUKVssMV0sIAogICAgICAgICBwcmVkaWN0b3IgPSBjYXNlX3doZW4ocHJlZGljdG9yID09ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiB+ICJHRlAiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAiYXJlYSIgfiAiQXJlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiIH4gIlB1cDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiB+ICJETkEiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAic2hhcGUiIH4gIlNoYXBlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gImRtIiB+ICJSYXRlIG9mIE1hdHVyYXRpb24iCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRX5wcmVkaWN0b3IpKSAlPiUgCiAgc3BsaXQoLiRzYW1wbGUpCgp2YXIuZXhwbGFpbmVkCmBgYAoKI3Bsb3R0aW5nIHRoZSB2YXJpYW5jZSBleHBsYWluZWQgCmBgYHtyfQpyZW1haW4ucmVnIDwtIGRhdGEuZnJhbWUoc2FtcGxlID0gYygieWVHRlAtQ0xOMiIsInllR0ZQLUNMTjIiLCJ5ZUdGUCIsInllR0ZQIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID0gYygiUmF0ZSBvZiBNYXR1cmF0aW9uIiwgIlNoYXBlIiwiU2hhcGUiLCJQdXAxIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgdmFyLmV4cCA9IHJlcCgwLDQpLAogICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUuUHIuLkYuID0gcmVwKDAsNCkpCnZhci5leHAucGx0IDwtIHZhci5leHBsYWluZWQgJT4lIAogIGJpbmRfcm93cygpICU+JSAKICBiaW5kX3Jvd3MoLixyZW1haW4ucmVnKSAlPiUgCiAgZmlsdGVyKHByZWRpY3RvciAhPSAiUmVzaWR1YWxzIikgJT4lIAogIGRwbHlyOjpzZWxlY3Qoc2FtcGxlLCBwcmVkaWN0b3IsIHZhci5leHAsdmFsdWUuUHIuLkYuKSAlPiUgCiAgbXV0YXRlKHNhbXBsZSA9IGZhY3RvcihzYW1wbGUgLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwieWVHRlAtQ0xOMiIsInllR0ZQIikpKSAlPiUgCiAgIyBtdXRhdGUodmFyLnBhbCA9IGlmZWxzZSh2YWx1ZS5Qci4uRi4gPCAwLjA1LCAiPDAuMDUiLCI+MC4wNSIpKSAlPiUgCiAgYXJyYW5nZShzYW1wbGUpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IHByZWRpY3RvciwgeSA9IHZhci5leHAgKSkrCiAgZ2VvbV9jb2wod2lkdGggPSAwLjUpKwogIGZhY2V0X3dyYXAofnNhbXBsZSwgc2NhbGVzID0gImZyZWUiKSsKICBzY2FsZV94X2Rpc2NyZXRlKGxhYmVscyA9IGZ1bmN0aW9uKHgpIHN0cl93cmFwKHgsIHdpZHRoID0gNSkpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSksCiAgICAgICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSkrCiAgeWxpbSgwLDIwKSsKICB5bGFiKCJWYXJpYW5jZSBleHBsYWluZWQgKCUpIikrCiAgeGxhYigiQ2VsbHVsYXIgZmVhdHVyZXMiKSsKICBsYWJzKHRpdGxlID0gIkIiKQp2YXIuZXhwLnBsdApgYGAKCgojcGxvdHM6IApgYGB7cn0KZ2ZwLjYuY29yLnBsdCA8LSBtbHIuZGYgJT4lCiAgbXV0YXRlKGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJjbG4yLjMiLCAiY2xuMi40IiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikpICU+JQogIGRwbHlyOjpzZWxlY3QodC5oYWxmLAogICAgICAgICByZWdyZXNzb3JzLAogICAgICAgICBkZWdyb24pICU+JQogIHJlbmFtZSgKICAgICJHRlAiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgIlB1cDEtdERpbWVyIiA9ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICJETkEiID0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiLAogICAgIkFyZWEiID0gImFyZWEiCiAgKSAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IDI6NykgJT4lCiAgbXV0YXRlKGRlZ3JvbiA9IGNhc2Vfd2hlbigKICAgICAgZGVncm9uICVpbiUgYygiY2xuMi4zIiwgImNsbjIuMiIsICJjbG4yIiwgImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICBkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAibU9EQyIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlIiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikgfiAieWVHRlAiCiAgICApLAogICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCAieWVHRlAtQ0xOMiIsICJ5ZUdGUCIpKQogICkgJT4lCiAgZmlsdGVyKCEobmFtZSAlaW4lIGMoInNoYXBlIiwiZG0iKSkpICU+JSAKICBnZ3Bsb3QoLiwgYWVzKHggPSB2YWx1ZSwgeSA9IHQuaGFsZikpICsKICAgICAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjIsIGd1aWRlcyA9IEYpICsKICAgICAgc3RhdF9jb3Ioc2l6ZSA9IDIpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICBmYWNldF93cmFwKGRlZ3JvbiB+IG5hbWUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSkpKwogIHlsYWIoIkhhbGYtbGlmZSBbbWluLl0iKSsKICB4bGFiKCJBLlUiKSsKICBsYWJzKHRpdGxlID0gIkEiKQogIApnZnAuNi5jb3IucGx0CmBgYAp3aXRoIHByb3RlaW4gaW5oaWJpdGlvbgpgYGB7cn0KIG1sci5kZiAlPiUKICBtdXRhdGUoZG0gPSBsb2cxMChkbSkpICU+JSAKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQyIpKSAlPiUKICAjIGZpbHRlcighKHRyZWF0bWVudCAlaW4lIGMoIm5vbmUiLCAiZG1zbzEiLCI1MHVNIikpLCAKICAgICAgICAgIyBpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAgCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbiwKICAgICAgICAgdHJlYXRtZW50KSAlPiUKICByZW5hbWUoCiAgICAiR0ZQIiA9ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiwKICAgICJQdXAxLXREaW1lciIgPSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIsCiAgICAiRE5BIiA9ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiwKICAgICJBcmVhIiA9ICJhcmVhIgogICkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAyOjcpICU+JQogIG11dGF0ZShkZWdyb24gPSBjYXNlX3doZW4oCiAgICBkZWdyb24gJWluJSBjKCJtT0RDIikgIH4gInllR0ZQLW1PREMiKSwKICAgIHRyZWF0bWVudCA9IGZhY3Rvcih0cmVhdG1lbnQsIGxldmVscyA9IGMoIm5vbmUiLCJkbXNvMSIsImRtc28yIiwiMXVNIiwiMi41dU0iLCI1dU0iLCI1MHVNIikpKSAlPiUKICBmaWx0ZXIoIShuYW1lICVpbiUgYygic2hhcGUiLCJkbSIpKSwKICAgICAgICAgISh0cmVhdG1lbnQgJWluJSBjKCJub25lIiwiZG1zbzEiLCI1MHVNIikpLCAKICAgICAgICAgdC5oYWxmIDwgMTMwKSAlPiUgCiAgCiAgZ2dwbG90KC4sIGFlcyh4ID0gdmFsdWUsIHkgPSB0LmhhbGYpKSArCiAgICAgIGdncG9pbnRkZW5zaXR5OjpnZW9tX3BvaW50ZGVuc2l0eShzaXplID0gMC4yLCBndWlkZXMgPSBGKSArCiAgICAgIHN0YXRfY29yKHNpemUgPSAyKSArCiAgICAgIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UsIGNvbG9yID0gInJlZDQiLCBzaXplID0gMC41KSsKICAgICAgZmFjZXRfZ3JpZCh0cmVhdG1lbnQgfiBuYW1lLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKwogIHlsYWIoIkhhbGYtTGlmZSBbbWluLl0iKSsKICB4bGFiKCJBLlUiKQoKYGBgCgojc3RlcEFJQyB3aXRoIHByb3RlYXNvbWUgaW5oaWJpdGlvbiBleHBlcmltZW50cwpXaXRoIGFsbCBmcCByZWdyZXNzb3JzCmBgYHtyfQp0ZW1wLmRmLmxpc3QuZG1zbyA8LSBtbHIuZGYgJT4lIAogICAgZmlsdGVyKHRyZWF0bWVudCAhPSAibm9uZSIsIHQuaGFsZiA8IDEzMCkgJT4lICAKICBzcGxpdCguJHRyZWF0bWVudCkKCmZ1bGwuc3RlcEFJQy5mcC5kbXNvIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QuZG1zbywgZnVuY3Rpb24oYSl7CiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCB0cmFjZSA9IFQpCn0pCgpgYGAKCndpdGggZnAgcmVncmVzc29ycyArIGNlbGx1YXIgc2hhcGUgCmBgYHtyfQp0ZW1wLmRmLmxpc3QuZG1zbyA8LSBtbHIuZGYgJT4lIAogICAgZmlsdGVyKHRyZWF0bWVudCAhPSAibm9uZSIsIHQuaGFsZiA8IDEzMCkgJT4lICAKICBzcGxpdCguJHRyZWF0bWVudCkKCmZ1bGwuc3RlcEFJQy5kbXNvIDwtIGxhcHBseSh0ZW1wLmRmLmxpc3QuZG1zbywgZnVuY3Rpb24oYSl7CiBzdGVwKGxtKHQuaGFsZiB+IC4sIGRhdGEgPSBhICU+JSAKICAgICBkcGx5cjo6c2VsZWN0KHJlZ3Jlc3NvcnMuZnAsCiAgICAgICAgICAgICAgICAgICB0LmhhbGYsCiAgICAgICAgICAgICAgICAgICAtZHksIAogICAgICAgICAgICAgICAgICAgLXRyZWF0bWVudCkpLCAKICAgICBkaXJlY3Rpb24gPSAiYmFja3dhcmQiLCB0cmFjZSA9IFQpCn0pCgoKYGBgCgpWYXJpYW5jZSBpbiB0LWhhbGYgZXhwbGFpbmVkIGJ5IGVhY2ggcmVncmVzc29yCmBgYHtyfQpmdWxsLnN0ZXBBSUMuZG1zbyAlPiUgCiAgbWFwKC4sIGFub3ZhICU+JSBhcy5kYXRhLmZyYW1lKSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJzYW1wbGUiKSAlPiUgCiAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJwcmVkaWN0b3IiKSAlPiUgCiAgIyBmaWx0ZXIoc2FtcGxlICVpbiUgYygibU9EQy4yIiwiY2xuMi4zIiwiY2xuMi40Iiwic3RhYmxlLjIiLCJzdGFibGUuMyIpKSAlPiUgCiAgZ3JvdXBfYnkoc2FtcGxlKSAlPiUgCiAgbXV0YXRlKHZhci5leHAgPSAodmFsdWUuU3VtLlNxL3N1bSh2YWx1ZS5TdW0uU3EpKSoxMDApICU+JSAKICBzcGxpdCguJHNhbXBsZSkKCmZ1bGwuc3RlcEFJQy5mcC5kbXNvICU+JSAKICBtYXAoLiwgYW5vdmEgJT4lIGFzLmRhdGEuZnJhbWUpICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInNhbXBsZSIpICU+JSAKICByb3duYW1lc190b19jb2x1bW4odmFyID0gInByZWRpY3RvciIpICU+JSAKICAjIGZpbHRlcihzYW1wbGUgJWluJSBjKCJtT0RDLjIiLCJjbG4yLjMiLCJjbG4yLjQiLCJzdGFibGUuMiIsInN0YWJsZS4zIikpICU+JSAKICBncm91cF9ieShzYW1wbGUpICU+JSAKICBtdXRhdGUodmFyLmV4cCA9ICh2YWx1ZS5TdW0uU3Evc3VtKHZhbHVlLlN1bS5TcSkpKjEwMCkgJT4lIAogIHNwbGl0KC4kc2FtcGxlKQoKYGBgCgpgYGB7cn0KZnVsbC5zdGVwQUlDLmRtc28gJT4lIAogIG1hcCguLCBhbm92YSAlPiUgYXMuZGF0YS5mcmFtZSkgJT4lIAogIGJpbmRfcm93cyguaWQgPSAic2FtcGxlIikgJT4lIAogIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicHJlZGljdG9yIikgJT4lIAogICMgZmlsdGVyKHNhbXBsZSAlaW4lIGMoIm1PREMuMiIsImNsbjIuMyIsImNsbjIuNCIsInN0YWJsZS4yIiwic3RhYmxlLjMiKSkgJT4lIAogIGdyb3VwX2J5KHNhbXBsZSkgJT4lIAogIG11dGF0ZSh2YXIuZXhwID0gKHZhbHVlLlN1bS5TcS9zdW0odmFsdWUuU3VtLlNxKSkqMTAwLCAKICAgICAgICAgcHJlZGljdG9yID0gc3RyX3NwbGl0KHByZWRpY3RvciwgcGF0dGVybiA9ICJcXC5cXC5cXC4iLCBzaW1wbGlmeSA9IFQpWywxXSwgCiAgICAgICAgIHByZWRpY3RvciA9IGNhc2Vfd2hlbihwcmVkaWN0b3IgPT0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciIH4gIkdGUCIgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJhcmVhIiB+ICJBcmVhIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAicmZwLm1lYW4uYmcuc3ViLnB1bmN0YSIgfiAiUHVwMSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVkaWN0b3IgPT0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiIH4gIkROQSIgLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJlZGljdG9yID09ICJzaGFwZSIgfiAiU2hhcGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWRpY3RvciA9PSAiZG0iIH4gIlJhdGUgb2YgTWF0dXJhdGlvbiIKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFfnByZWRpY3RvcikpICU+JSAKICBzcGxpdCguJHNhbXBsZSkKYGBgCgpgYGB7cn0KbWxyLmRmICU+JQogIG11dGF0ZShkbSA9IGxvZzEwKGRtKSkgJT4lIAogIGZpbHRlcihkZWdyb24gJWluJSBjICgibU9EQyIpICkgJT4lCiAgZmlsdGVyKCEodHJlYXRtZW50ICVpbiUgYygibm9uZSIsICJkbXNvMSIsIjUwdU0iKSksIAogICAgICAgICBpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwKICAgICAgICAgcmVncmVzc29ycywKICAgICAgICAgZGVncm9uLAogICAgICAgICB0cmVhdG1lbnQpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IGFyZWEsIHkgPSByZnAubWVhbi5iZy5zdWIucHVuY3RhKSkrCiAgZ2VvbV9wb2ludCgpKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikrCiAgZmFjZXRfd3JhcCh+dHJlYXRtZW50KSsKICBzdGF0X2NvcigpCmBgYAoKCiNnZ3BhaXJzIApgYGB7cn0KI3RvIGJlIHVzZWQgd2l0aCBnZ3BhaXJzCm15X2ZuIDwtIGZ1bmN0aW9uKGRhdGEsIG1hcHBpbmcsIC4uLil7CiAgcCA8LSBnZ3Bsb3QoZGF0YSA9IGRhdGEsIG1hcHBpbmcgPSBtYXBwaW5nKSArIAogICAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjEpKwogICAgIyBnZW9tX3BvaW50KHNpemUgPSAwLjEsIGFscGhhID0gMC4xKSArIAogICAgZ2VvbV9zbW9vdGgobWV0aG9kPSJsbSIsICBjb2xvcj0icmVkNCIsIHNlID0gRkFMU0UsIGx3ZCA9IDAuNSkrCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCiAgcAp9CgpnZnAuYXJlYS5jb3IuZ2dQYWlyIDwtIG1sci5kZiAlPiUKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQy4yIiwgImNsbjIuMyIsICJjbG4yLjQiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbikgJT4lCiAgcmVuYW1lKAogICAgIkdGUCIgPSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAiUHVwMS10RGltZXIiID0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgIkROQSIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIsCiAgICAiQXJlYSIgPSAiYXJlYSIKICApICU+JQogIGRwbHlyOjpzZWxlY3QoQXJlYSwgRE5BLCBgUHVwMS10RGltZXJgLEdGUCxkZWdyb24gKSAlPiUgCiAgbXV0YXRlKAogICAgZGVncm9uID0gY2FzZV93aGVuKAogICAgICBkZWdyb24gJWluJSBjKCJjbG4yLjMiLCAiY2xuMi40IikgfiAieWVHRlAtQ0xOMiIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlLjIiLCAic3RhYmxlLjMiKSB+ICJ5ZUdGUCIKICAgICksCiAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygieWVHRlAtbU9EQyIsICJ5ZUdGUC1DTE4yIiwgInllR0ZQIikpCiAgKSAlPiUKICBzcGxpdCguJGRlZ3JvbikgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSAlPiUgCiAgICAgIGdncGFpcnMoLiwKICAgICAgICAgICMgbGVnZW5kID0gNSwKICAgICAgICAgIGNvbHVtbnMgPSAxOjQsCiAgICAgICAgICAjIG1hcHBpbmcgPSBnZ3Bsb3QyOjphZXMoY29sb3IgPSBSZXBsaWNhdGUpLAogICAgICAgICAgbG93ZXIgPSBsaXN0KGNvbnRpbnVvdXMgPSBteV9mbiwKICAgICAgICAgICAgICAgICAgICAgIGRpc2NyZXRlID0gImJsYW5rIiwgCiAgICAgICAgICAgICAgICAgICAgICBjb21ibz0iYmxhbmsiKSwgCiAgICAgICAgICAjIHVwcGVyID0gImJsYW5rIiwKICAgICAgICAgICMgZGlhZyA9IE5VTEwsCiAgICAgICAgICAgZGlhZyA9IGxpc3QoZGlzY3JldGU9ImJhckRpYWciLAogICAgICAgICAgICAgICAgICAgICAgY29udGludW91cyA9IHdyYXAoImRlbnNpdHlEaWFnIiwgYWxwaGE9MC41ICkpLAogICAgICAgICAgdXBwZXIgPSBsaXN0KGRpc2NyZXRlPSB3cmFwKCJiYXJEaWFnIiAsIG91dGxpZXIuc2l6ZSA9IDAuNSksCiAgICAgICAgICAgICAgICAgICAgICAgY29tYm8gPSB3cmFwKCJib3hfbm9fZmFjZXQiLCBvdXRsaWVyLnNpemUgPSAwLjUpLAogICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVvdXMgPSB3cmFwKCJjb3IiLCBkaXNwbGF5X2dyaWQgPSBGQUxTRSwgc2l6ZSA9IDIuNSAsIG1ldGhvZCA9ICJwZWFyc29uIiwgY29sb3IgPSAicmVkNCIpKSwKICAgICAgICAgIGxhYmVsbGVyID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAyLCBtdWx0aV9saW5lID0gVFJVRSkpKwogIHRoZW1lX2J3KCkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLAogICAgICAgIHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCwgaGp1c3QgPSAxKSkrCiAgICAgIGxhYnModGl0bGUgPSBhJGRlZ3JvblsxXSkKICB9KQogIApnZnAuYXJlYS5jb3IuZ2dQYWlyCmBgYApgYGB7cn0KZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1tT0RDYCwgZmlsZW5hbWUgPSAiZ2ZwX21PRENfNENvcl9nZ1AucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1tT0RDYCwgZmlsZW5hbWUgPSAiZ2ZwX21PRENfNENvcl9nZ1AucGRmIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1DTE4yYCwgZmlsZW5hbWUgPSAiZ2ZwX2NsbjJfNENvcl9nZ1AucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUC1DTE4yYCwgZmlsZW5hbWUgPSAiZ2ZwX2NsbjJfNENvcl9nZ1AucGRmIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNCwgaGVpZ2h0ID0gMy41KQoKZ2dzYXZlKHBsb3QgPSBnZnAuYXJlYS5jb3IuZ2dQYWlyJGB5ZUdGUGAsIGZpbGVuYW1lID0gImdmcF80Q29yX2dnUC5wbmciLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA0LCBoZWlnaHQgPSAzLjUpCgpnZ3NhdmUocGxvdCA9IGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQYCwgZmlsZW5hbWUgPSAiZ2ZwXzRDb3JfZ2dQLnBkZiIsIHBhdGggPSAifi9wbG90cy9wYXBlcjEvZmlndXJlcy9maWdfMi8iLCB3aWR0aCA9IDQsIGhlaWdodCA9IDMuNSkKYGBgCgpgYGB7cn0KdGVzdC5nZ1AgPC0gKHdyYXBfZWxlbWVudHMoZ2dtYXRyaXhfZ3RhYmxlKGdmcC5hcmVhLmNvci5nZ1BhaXIkYHllR0ZQLW1PRENgKSl8d3JhcF9lbGVtZW50cyhnZ21hdHJpeF9ndGFibGUoZ2ZwLmFyZWEuY29yLmdnUGFpciRgeWVHRlAtQ0xOMmApKXwgd3JhcF9lbGVtZW50cyhnZ21hdHJpeF9ndGFibGUoZ2ZwLmFyZWEuY29yLmdnUGFpciR5ZUdGUCkpKSsKIHBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gIkEiKQpgYGAKCmBgYHtyfQpnZ3NhdmUocGxvdCA9IHRlc3QuZ2dQLCBmaWxlbmFtZSA9ICJ0ZXN0X2dnUC5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDMpCmBgYAoKI2FyZWEgdnMgcHVwMSB2cyBkbmEgdnMgZ2ZwCmBgYHtyfQpkZl9jb3JTdXBfZmlnIDwtIG1sci5kZiAlPiUKICBmaWx0ZXIoZGVncm9uICVpbiUgYygibU9EQy4yIiwgImNsbjIuMyIsICJjbG4yLjQiLCAic3RhYmxlLjIiLCAic3RhYmxlLjMiKSkgJT4lCiAgZHBseXI6OnNlbGVjdCh0LmhhbGYsCiAgICAgICAgIHJlZ3Jlc3NvcnMsCiAgICAgICAgIGRlZ3JvbikgJT4lCiAgcmVuYW1lKAogICAgIkdGUCIgPSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIsCiAgICAiUHVwMS10RGltZXIiID0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiLAogICAgIkROQSIgPSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIsCiAgICAiQXJlYSIgPSAiYXJlYSIKICApICU+JQogIGRwbHlyOjpzZWxlY3QoQXJlYSwgRE5BLCBgUHVwMS10RGltZXJgLEdGUCxkZWdyb24gKSAlPiUgCiAgbXV0YXRlKAogICAgZGVncm9uID0gY2FzZV93aGVuKAogICAgICBkZWdyb24gJWluJSBjKCJjbG4yLjMiLCAiY2xuMi40IikgfiAieWVHRlAtQ0xOMiIsCiAgICAgIGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlLjIiLCAic3RhYmxlLjMiKSB+ICJ5ZUdGUCIKICAgICksCiAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uICwgbGV2ZWxzID0gYygieWVHRlAtbU9EQyIsICJ5ZUdGUC1DTE4yIiwgInllR0ZQIikpCiAgKSAKYGBgCgpgYGB7cn0KCmFyZWEucHVwMSA8LSBkZl9jb3JTdXBfZmlnICU+JSAKICBmaWx0ZXIoZGVncm9uID09ICJ5ZUdGUC1tT0RDIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gQXJlYSwgeSA9IGBQdXAxLXREaW1lcmApKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpKSsKICB5bGFiKCJQdXAxLXREaW1lciBbQS5VXSIpKwogIHhsYWIoIkFyZWEgW0EuVV0iKQoKZG5hLnB1cDEgPC0gZGZfY29yU3VwX2ZpZyAlPiUgCiAgZmlsdGVyKGRlZ3JvbiA9PSAieWVHRlAtbU9EQyIpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IEROQSwgeSA9IGBQdXAxLXREaW1lcmApKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgICAgIHRoZW1lX2J3KCkgKwogICAgICBsYWJzKHggPSBOVUxMKSArCiAgICAgIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpLAogICAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwKSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCgyLCJtbSIpLCAKICAgICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAgICAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpKSsKICB5bGFiKCJQdXAxLXREaW1lciBbQS5VXSIpKwogIHhsYWIoIkROQSBbQS5VXSIpCgpkbmEuYXJlYSA8LSBkZl9jb3JTdXBfZmlnICU+JQogIGZpbHRlcihkZWdyb24gPT0gInllR0ZQLW1PREMiKSAlPiUgCiAgZ2dwbG90KC4sYWVzKHggPSBETkEsIHkgPSBBcmVhKSkrCiAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjIsIGd1aWRlcyA9IEYpICsKICAgICAgc3RhdF9jb3Ioc2l6ZSA9IDMpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICB0aGVtZV9idygpICsKICAgICAgbGFicyh4ID0gTlVMTCkgKwogICAgICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMCksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoMiwibW0iKSwgCiAgICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgICAgICAgICAgIGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShzaXplID0gMC4xKSkrCiAgeWxhYigiQXJlYSBbQS5VXSIpKwogIHhsYWIoIkROQSBbQS5VXSIpCmBgYAoKYGBge3J9CmdmcEludC5jb3IucGx0IDwtIGRmX2NvclN1cF9maWcgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gMTozKSAlPiUgCiAgIyBmaWx0ZXIoZGVncm9uID09ICJ5ZUdGUC1tT0RDIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gdmFsdWUsIHkgPSBHRlApKSsKICBnZ3BvaW50ZGVuc2l0eTo6Z2VvbV9wb2ludGRlbnNpdHkoc2l6ZSA9IDAuMiwgZ3VpZGVzID0gRikgKwogICAgICBzdGF0X2NvcihzaXplID0gMykgKwogICAgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEZBTFNFLCBjb2xvciA9ICJyZWQ0Iiwgc2l6ZSA9IDAuNSkrCiAgZmFjZXRfd3JhcChkZWdyb25+bmFtZSwgc2NhbGVzID0gImZyZWUiKSsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgICAgICBheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoc2l6ZSA9IDAuMSkpKwogIHhsYWIoIkEuVSIpCmBgYAoKYGBge3J9CnRlc3RfY29yIDwtICgoYXJlYS5wdXAxfGRuYS5wdXAxfGRuYS5hcmVhKS9nZnBJbnQuY29yLnBsdCkrCiAgcGxvdF9sYXlvdXQoaGVpZ2h0cyA9IGMoMC4yLCAwLjgpKSsKICBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJBIikKCmdnc2F2ZShwbG90ID0gdGVzdF9jb3IsIGZpbGVuYW1lID0gImFyZWEucHVwMS5kbmEuZ2ZwX2Nvci5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA2LjUsIGhlaWdodCA9IDcpCmBgYAoKCiNQYXJ0aWFsIGNvcnJlbGF0aW9ucwpwcGNvcgpgYGB7cn0KI3BhcnRpYWwgY29ycmVsYXRpb25zCnBwQ29yLmxpc3QgPC0gbWxyLmRmMiAlPiUgCiAgZmlsdGVyKHRyZWF0bWVudCA9PSAibm9uZSIpICU+JSBzcGxpdCguJGRlZ3JvbikgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsICBkYXBpLnN1bS5iZy5zdWIucHVuY3RhLCByZnAubWVhbi5iZy5zdWIucHVuY3RhLCBnZnAubWVhbi5iZy5hZi5zdWIubmV3KSAlPiUgCiAgICAgIG5hLm9taXQoKQogICAgcHBjb3I6OnBjb3IoYSkKICB9KQoKI2NvcnJlbGF0aW9ucwpjb3IuYWxsIDwtIG1sci5kZjIgJT4lIAogIGZpbHRlcih0cmVhdG1lbnQgPT0gIm5vbmUiKSAlPiUgIAogIHNwbGl0KC4kZGVncm9uKSAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEscmZwLm1lYW4uYmcuc3ViLnB1bmN0YSwgZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldykgJT4lIAogICAgICBuYS5vbWl0KCkKICAgICBjb3IoYSkKICB9KQoKYGBgCgpgYGB7cn0KcHBDb3IuZGYgPC0gcHBDb3IubGlzdCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJGVzdGltYXRlICU+JSAKICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgICAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJyZWdyZXNzb3IiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QodC5oYWxmLCByZWdyZXNzb3IpICU+JSAKICAgICAgbGVmdF9qb2luKC4sYSRwLnZhbHVlJT4lIAogICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICAgICAgICAgICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgICAgICAgICAgICAgcmVuYW1lKCJwLnZhbHVlIiA9ICJ0LmhhbGYiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QocC52YWx1ZSwgcmVncmVzc29yKSwgYnkgPSAicmVncmVzc29yIikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJkZWdyb24iKQoKc2luZ2xlLmNvcmUuZGYgPC0gY29yLmFsbCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJT4lIAogICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIHJlZ3Jlc3NvcikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJkZWdyb24iKSAlPiUgCiAgcmVuYW1lKCJzaW5nbGUuY29yZSI9InQuaGFsZiIpCgpgYGAKCgoKYGBge3J9CnBwQ29vci5maWcgPC0gcHBDb3IuZGYgJT4lIAogIGxlZnRfam9pbiguLHNpbmdsZS5jb3JlLmRmLCBieSA9IGMoImRlZ3JvbiIsInJlZ3Jlc3NvciIpKSAlPiUgCiAgcmVuYW1lKCJQYXJ0aWFsLVBhcml3aXNlIj0idC5oYWxmIiwKICAgICAgICAgIlN0YW5kYXJkLVBhcml3aXNlIiA9ICJzaW5nbGUuY29yZSIpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoIlBhcnRpYWwtUGFyaXdpc2UiLCJTdGFuZGFyZC1QYXJpd2lzZSIpKSAlPiUgCiAgIG11dGF0ZShyZWdyZXNzb3IgPSBjYXNlX3doZW4ocmVncmVzc29yID09ICJnZnAubWVhbi5iZy5hZi5zdWIubmV3IiB+ICJHRlAiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAiYXJlYSIgfiAiQXJlYSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gInJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEiIH4gIlB1cDEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVncmVzc29yID09ICJkYXBpLnN1bS5iZy5zdWIucHVuY3RhIiB+ICJETkEiICwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAidC5oYWxmIiB+ICJoYWxmLWxpZmUiKSwgCiAgICAgICAgICBkZWdyb24gPSBmYWN0b3IoZGVncm9uLCBsZXZlbHMgPSBjKCJ5ZUdGUC1tT0RDIiwieWVHRlAtQ0xOMiIsInllR0ZQIikpLCAKICAgICAgICAgIG5hbWUgPSBmYWN0b3IobmFtZSAsIGxldmVscyA9IGMoIlN0YW5kYXJkLVBhcml3aXNlIiwgIlBhcnRpYWwtUGFyaXdpc2UiKSksIAogICAgICAgICAgc2lnID0gc3RhcnMucHZhbChwLnZhbHVlKSwgCiAgICAgICAgICBzaWcgPSBpZmVsc2Uoc2lnID09ICIgIiwgIk5TIiwgc2lnKSkgJT4lIAogICMgZmlsdGVyKHAudmFsdWUgPCAwLjA1KSAlPiUgCiAgZmlsdGVyKHJlZ3Jlc3NvciAhPSAiaGFsZi1saWZlIikgJT4lIAogIGdncGxvdCguLGFlcyh4ID0gcmVncmVzc29yICwgeSA9IHZhbHVlLCBmaWxsID0gbmFtZSkpKwogIGdlb21fY29sKHdpZHRoID0gMC41LCBwb3NpdGlvbiA9ICJkb2RnZSIpKwogIGZhY2V0X3dyYXAofmRlZ3JvbikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCwgc2l6ZSA9IDAuMSkrCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgtMC41LDAuNSwgYnkgPSAwLjEpKSsKICB0aGVtZV9wdWJyKCkrCiAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGxlZ2VuZC5rZXkuc2l6ZSA9IHVuaXQoNCwibW0iKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAidG9wIiwgCiAgICAgICAgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKHNpemUgPSAwLjEpLAogICAgICAgIHN0cmlwLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoImxpZ2h0c3RlZWxibHVlNCIgLCIgc3RlZWxibHVlNCIpLCBuYW1lID0gTlVMTCkrCiAgeWxhYigiQ29ycmVsYXRpb24gd2l0aCBIYWxmLWxpZmUgIikrCiAgeGxhYigiQ2VsbHVsYXIgZmVhdHVyZXMiKSsKICBsYWJzKHRpdGxlID0gIkMiKQoKcHBDb29yLmZpZwpgYGAKI3BhdGNod29yayBmb3IgNCBjZWxsdWxhciBmZWF0dXJlcyAoYXJlYSwgZ2ZwLCBkYXBpLCBwdXAxKSBhbmQgdC1oYWxmIAoKYGBge3IgZmlnLndpZHRoPSA1LCBmaWcuaGVpZ2h0PSA2fQpnZnAuNGNvci5oZi5wcENvci5wbHQgPC0gKGdmcC42LmNvci5wbHQvdmFyLmV4cC5wbHQvcHBDb29yLmZpZykrCiAgcGxvdF9sYXlvdXQoIGhlaWdodHMgPSBjKDAuNiwwLjIsIDAuMikpCiAgIyBwbG90X2Fubm90YXRpb24odGFnX2xldmVscyA9ICJBIikKCmdmcC40Y29yLmhmLnBwQ29yLnBsdApgYGAKCmBgYHtyfQpnZ3NhdmUocGxvdCA9IGdmcC40Y29yLmhmLnBwQ29yLnBsdCwgZmlsZW5hbWUgPSAiZ2ZwXzRjb3JfaGFsZkxpZmVfcHBjb3IucG5nIiwgcGF0aCA9ICJ+L3Bsb3RzL3BhcGVyMS9maWd1cmVzL2ZpZ18yLyIsIHdpZHRoID0gNywgaGVpZ2h0ID0gOSkKCmdnc2F2ZShwbG90ID0gZ2ZwLjRjb3IuaGYucHBDb3IucGx0LCBmaWxlbmFtZSA9ICJnZnBfNGNvcl9oYWxmTGlmZV9wcGNvci5wZGYiLCBwYXRoID0gIn4vcGxvdHMvcGFwZXIxL2ZpZ3VyZXMvZmlnXzIvIiwgd2lkdGggPSA3LCBoZWlnaHQgPSA5KQpgYGAKCiN3aXRoIHByb3RlaW4gaW5oaWJpb24KYGBge3J9CnBwQ29yLlBydEluLmxpc3QgPC0gbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgIAogIGZpbHRlcihpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBzcGxpdCguJHRyZWF0bWVudCkgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JQogICAgICBuYS5vbWl0KCkKICAgIHBwY29yOjpwY29yKGEpCiAgfSkKCmNvci5QcnRJbi5hbGwgPC0gbWxyLmRmICU+JSAKICAgIGZpbHRlcih0cmVhdG1lbnQgIT0gIm5vbmUiKSAlPiUgIAogIGZpbHRlcihpZmVsc2UodHJlYXRtZW50ID09ICI1dU0iLCB0LmhhbGYgPCAxMzguNjI5NCwgdC5oYWxmID09IHQuaGFsZikpICU+JSAKICBzcGxpdCguJHRyZWF0bWVudCkgJT4lIAogIG1hcCguLGZ1bmN0aW9uKGEpewogICAgYSA8LSBhICU+JSAKICAgICAgZHBseXI6OnNlbGVjdCh0LmhhbGYsIGFyZWEsIGRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEsIHJmcC5tZWFuLmJnLnN1Yi5wdW5jdGEsIGdmcC5tZWFuLmJnLmFmLnN1Yi5uZXcpICU+JSAKICAgICAgbmEub21pdCgpCiAgICBjb3IoYSkKICB9KQoKYGBgCgpgYGB7cn0KcHBDb3IuUHJ0SW4uZGYgPC0gcHBDb3IuUHJ0SW4ubGlzdCAlPiUgCiAgbWFwKC4sZnVuY3Rpb24oYSl7CiAgICBhJGVzdGltYXRlICU+JSAKICAgICAgYXMuZGF0YS5mcmFtZSgpICU+JSAKICAgICAgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJyZWdyZXNzb3IiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QodC5oYWxmLCByZWdyZXNzb3IpICU+JSAKICAgICAgbGVmdF9qb2luKC4sYSRwLnZhbHVlJT4lIAogICAgICAgICAgICAgICAgICBhcy5kYXRhLmZyYW1lKCkgJT4lIAogICAgICAgICAgICAgICAgICByb3duYW1lc190b19jb2x1bW4odmFyID0gInJlZ3Jlc3NvciIpICU+JSAKICAgICAgICAgICAgICAgICAgcmVuYW1lKCJwLnZhbHVlIiA9ICJ0LmhhbGYiKSAlPiUgCiAgICAgIGRwbHlyOjpzZWxlY3QocC52YWx1ZSwgcmVncmVzc29yKSwgYnkgPSAicmVncmVzc29yIikKICB9KSAlPiUgCiAgYmluZF9yb3dzKC5pZCA9ICJ0cmVhdG1lbnQiKQoKc2luZ2xlLmNvcmUuUHJ0bi5kZiA8LSBjb3IuUHJ0SW4uYWxsICU+JSAKICBtYXAoLixmdW5jdGlvbihhKXsKICAgIGElPiUgCiAgICAgIGFzLmRhdGEuZnJhbWUoKSAlPiUgCiAgICAgIHJvd25hbWVzX3RvX2NvbHVtbih2YXIgPSAicmVncmVzc29yIikgJT4lIAogICAgICBkcGx5cjo6c2VsZWN0KHQuaGFsZiwgcmVncmVzc29yKQogIH0pICU+JSAKICBiaW5kX3Jvd3MoLmlkID0gInRyZWF0bWVudCIpICU+JSAKICByZW5hbWUoInNpbmdsZS5jb3JlIj0idC5oYWxmIikKYGBgCgpjb3JyZWxhdGlvbiBvZiBwdXAxIHdpdGggbU9EQyB3aXRoIHRyZWF0ZWQgd2l0aCBwcm90ZWFzb21lIGluaGliaXRvcnMKYGBge3J9CnBwY29yLmZpZy5kZiA8LSBwcENvci5QcnRJbi5kZiAlPiUgCiAgbGVmdF9qb2luKC4sc2luZ2xlLmNvcmUuUHJ0bi5kZiwgYnkgPSBjKCJ0cmVhdG1lbnQiLCJyZWdyZXNzb3IiKSkgJT4lIAogIGZpbHRlcighKHRyZWF0bWVudCAlaW4lIGMoImRtc28xIiwiNTB1TSIpKSkgJT4lIAogIHJlbmFtZSgiUGFydGlhbC1QYXJpd2lzZSI9InQuaGFsZiIsCiAgICAgICAgICJTdGFuZGFyZC1QYXJpd2lzZSIgPSAic2luZ2xlLmNvcmUiKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJQYXJ0aWFsLVBhcml3aXNlIiwiU3RhbmRhcmQtUGFyaXdpc2UiKSkgJT4lIAogICBtdXRhdGUocmVncmVzc29yID0gY2FzZV93aGVuKHJlZ3Jlc3NvciA9PSAiZ2ZwLm1lYW4uYmcuYWYuc3ViLm5ldyIgfiAiR0ZQIiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gImFyZWEiIH4gIkFyZWEiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVncmVzc29yID09ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiB+ICJQdXAxIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlZ3Jlc3NvciA9PSAiZGFwaS5zdW0uYmcuc3ViLnB1bmN0YSIgfiAiRE5BIiAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWdyZXNzb3IgPT0gInQuaGFsZiIgfiAiaGFsZi1saWZlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUUlVFIH4gcmVncmVzc29yKSwgCiAgICAgICAgICB0cmVhdG1lbnQgPSBmYWN0b3IodHJlYXRtZW50LCBsZXZlbHMgPSBjKCJkbXNvMSIsIjUwdU0iLCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIikpLCAKICAgICAgICAgIG5hbWUgPSBmYWN0b3IobmFtZSAsIGxldmVscyA9IGMoIlN0YW5kYXJkLVBhcml3aXNlIiwgIlBhcnRpYWwtUGFyaXdpc2UiKSksIAogICAgICAgICAgc2lnID0gc3RhcnMucHZhbChwLnZhbHVlKSwgCiAgICAgICAgICBzaWcgPSBpZmVsc2Uoc2lnID09ICJcICIsICJOLlMiLCBzaWcpKQogICAgICAgICAgIyBuZXcudmFsdWUgPSBpZmVsc2UoKG5hbWUgPT0gIlBhcnRpYWwtUGFyaXdpc2UiICYgcC52YWx1ZSA+IDAuMDUpLCAwLCB2YWx1ZSkpICU+JSAKICAjIGZpbHRlcihwLnZhbHVlIDwgMC4wNSkgJT4lIApwcGNvci5maWcuZGYgJT4lIAogIGZpbHRlcighKHJlZ3Jlc3NvciAlaW4lIGMoImhhbGYtbGlmZSIsICJzaGFwZSIpKSwgCiAgICAgICAgIHJlZ3Jlc3NvciA9PSAiUHVwMSIsIAogICAgICAgICB0cmVhdG1lbnQgJWluJSBjKCJkbXNvMiIsIjF1TSIsIjIuNXVNIiwiNXVNIikpICU+JSAKICBnZ3Bsb3QoLixhZXMoeCA9IHRyZWF0bWVudCAsIHkgPXZhbHVlLCBmaWxsID0gbmFtZSkpKwogIGdlb21fY29sKHdpZHRoID0gMC41LCBwb3NpdGlvbiA9ICJkb2RnZSIpKwogIGdlb21fdGV4dChkYXRhID0gcHBjb3IuZmlnLmRmICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIoIShyZWdyZXNzb3IgJWluJSBjKCJoYWxmLWxpZmUiLCAic2hhcGUiKSksIAogICAgICAgICByZWdyZXNzb3IgPT0gIlB1cDEiLCAKICAgICAgICAgdHJlYXRtZW50ICVpbiUgYygiZG1zbzIiLCIxdU0iLCIyLjV1TSIsIjV1TSIpKSAsIAogICAgICAgICBhZXMobGFiZWwgPSBzaWcpLCBudWRnZV94ID0gLTAuMSkrCiAgIyBmYWNldF93cmFwKH50cmVhdG1lbnQsIG5yb3cgPSAxKSsKICBzY2FsZV95X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKC0wLjUsMC41LCBieSA9IDAuMSkpKwogIHRoZW1lX3B1YnIoKSsKICB0aGVtZSh0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSwKICAgICAgICAgICAgbGVnZW5kLmtleS5zaXplID0gdW5pdCg0LCJtbSIpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKSsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJsaWdodHN0ZWVsYmx1ZTQiICwiIHN0ZWVsYmx1ZTQiKSwgbmFtZSA9IE5VTEwpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApKwogIHlsYWIoIkNvcnJlbGF0aW9uIG9mIFB1cDEgd2l0aCBIYWxmLWxpZmUgIikrCiAgeGxhYigiUHJvdGVpbiBpbmhpYml0b3IgdHJlYXRtZW50IChNRzEzMikiKQpgYGAKCiN3aGVuIHlvdSBub3JtYWxpemUgcHVwMSB3aXRoIHRoZSBhcmVhCmBgYHtyfQptbHIuZGYgJT4lCiAgbXV0YXRlKGRtID0gbG9nMTAoZG0pKSAlPiUgCiAgZmlsdGVyKGRlZ3JvbiAlaW4lIGMoIm1PREMuMiIsICJjbG4yLjMiLCAiY2xuMi40IiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikpICU+JQogIGRwbHlyOjpzZWxlY3QodC5oYWxmLAogICAgICAgICByZWdyZXNzb3JzLAogICAgICAgICBkZWdyb24pICU+JQogIHJlbmFtZSgKICAgICJHRlAiID0gImdmcC5tZWFuLmJnLmFmLnN1Yi5uZXciLAogICAgIlB1cDEtdERpbWVyIiA9ICJyZnAubWVhbi5iZy5zdWIucHVuY3RhIiwKICAgICJETkEiID0gImRhcGkuc3VtLmJnLnN1Yi5wdW5jdGEiLAogICAgIkFyZWEiID0gImFyZWEiCiAgKSAlPiUKICBtdXRhdGUobm9ybS5wdXAxID0gYFB1cDEtdERpbWVyYC9BcmVhKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKDI6Nyw5KSkgJT4lCiAgbXV0YXRlKGRlZ3JvbiA9IGNhc2Vfd2hlbigKICAgICAgZGVncm9uICVpbiUgYygiY2xuMi4zIiwgImNsbjIuMiIsICJjbG4yIiwgImNsbjIuNCIpIH4gInllR0ZQLUNMTjIiLAogICAgICBkZWdyb24gJWluJSBjKCJtT0RDLjIiLCAibU9EQyIpICB+ICJ5ZUdGUC1tT0RDIiwKICAgICAgZGVncm9uICVpbiUgYygic3RhYmxlIiwgInN0YWJsZS4yIiwgInN0YWJsZS4zIikgfiAieWVHRlAiCiAgICApLAogICAgZGVncm9uID0gZmFjdG9yKGRlZ3JvbiAsIGxldmVscyA9IGMoInllR0ZQLW1PREMiLCAieWVHRlAtQ0xOMiIsICJ5ZUdGUCIpKQogICkgJT4lCiAgZmlsdGVyKCEobmFtZSAlaW4lIGMoInNoYXBlIiwiZG0iKSkpICU+JSAKICBnZ3Bsb3QoLiwgYWVzKHggPSB2YWx1ZSwgeSA9IHQuaGFsZikpICsKICAgICAgZ2dwb2ludGRlbnNpdHk6Omdlb21fcG9pbnRkZW5zaXR5KHNpemUgPSAwLjIsIGd1aWRlcyA9IEYpICsKICAgICAgc3RhdF9jb3Ioc2l6ZSA9IDIpICsKICAgICAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGQUxTRSwgY29sb3IgPSAicmVkNCIsIHNpemUgPSAwLjUpKwogICAgICBmYWNldF93cmFwKGRlZ3JvbiB+IG5hbWUsIHNjYWxlcyA9ICJmcmVlIiwgbmNvbCA9IDQpICsKICAgICAgdGhlbWVfYncoKSArCiAgICAgIGxhYnMoeCA9IE5VTEwpICsKICAgICAgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCksCiAgICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzApLAogICAgICAgICAgICBsZWdlbmQua2V5LnNpemUgPSB1bml0KDIsIm1tIiksIAogICAgICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpKwogIHlsYWIoIkhhbGYtTGlmZSBbbWluLl0iKSsKICB4bGFiKCJBLlUiKQpgYGAKCg==